﻿(function () {
    "use strict";

    // 定义一个下载队列
    // Global array used to persist(存储) operations.
    var downloadOperations = [];
    var DownloadOptionList = new Array();

    WinJS.UI.Pages.define("/pages/pages.html", {
        // This function is called whenever a user navigates to this page. It
        // populates the page elements with the app's data.
        init: function (element, options) {
            console.log("pages:init，页面初始化时");
            //定义数据,用于存储获取到的json和生成的img url
            WinJS.Namespace.define("updateStorageFile",
            {
                dataTitle: "imgStorageData.txt",
                getUrl: "/json/1.json",
                dataFile: null,
                dataJson: null,
                isDataOK: 0,//是否获取数据成功
                addFunc: null,
                dataTemp: new WinJS.Binding.List(null)
            });
        },
        ready: function (element, options) {
            console.log("pages:ready，页面初加载完成后");

            //从服务器读取获取
            //获取原生json数据，存储到名字空间imgStorageFile
            getDataFromJson(updateStorageFile, updateStorageFileOkFunc);

        },
        unload: function () {

        }
    });

    //TODO: 开始下载函数
    function startDownload(option, folderObj) {
        // BackgroundTransferPriority.default：0，枚举值，操作的默认优先级别设置。默认情况下，在创建新操作后，该操作将放置于当前传输队列的末尾。
        // var promise = downloadFile(Windows.Networking.BackgroundTransfer.BackgroundTransferPriority.default, false, option);

        // 初始化下载操作对象
        var newDownload = new DownloadOperation();

        var fileName = option.fileName;
        if (fileName === "") {
            displayError("A local file name is required.");
            return;
        }

        // Validating the URI is required since it was received from an untrusted source (user input).
        // The URI is validated by catching exceptions thrown by the Uri constructor.
        // Note that when enabling the text box users may provide URIs to machines on the intrAnet that require the
        // "Home or Work Networking" capability.
        var uri = null;
        var uriString = option.uriString;

        try {
            //new Windows.Foundation.Uri()启动 URI 的默认应用//https://msdn.microsoft.com/zh-cn/library/windows/apps/hh452690.aspx?f=255&MSPPError=-2147217396
            uri = new Windows.Foundation.Uri(uriString);
        } catch (error) {
            console.log("Error: Invalid URI. " + error.message);
            return;
        }

        var folderObj = folderObj;
        var priority = Windows.Networking.BackgroundTransfer.BackgroundTransferPriority.default;//0，枚举值，操作默认优先级别
        var requestUnconstrainedTransfer = false;
        var promise = newDownload.start(uri, folderObj, fileName, priority, requestUnconstrainedTransfer);

        // Persist（存储） the download operation in the global array.
        downloadOperations.push(newDownload);

        return promise;
    }



    //从服务器读取数据，并处理
    function updateStorageFileOkFunc(data) {
        // Enumerate outstanding downloads.
        // BackgroundDownloader 类：https://msdn.microsoft.com/zh-cn/library/windows/apps/windows.networking.backgroundtransfer.backgrounddownloader.aspx
        // getCurrentDownloadsAsync(),返回当前应用程序实例的挂起下载集合。
        // 返回值：IAsyncOperation < IVectorView >
        //var localFolder = Windows.Storage.ApplicationData.current.localFolder;
        // Enumerate（枚举） outstanding downloads.
        // getCurrentDownloadsAsync() -返回未与组关联的挂起下载的集合。
        // Returns a collection of pending downloads that are not associated with a group.
        //Windows.Networking.BackgroundTransfer.BackgroundDownloader.getCurrentDownloadsAsync().done(function (downloads) {
        //    // If downloads from previous application state exist, reassign callbacks and persist to global array.
        //    for (var i = 0; i < downloads.size; i++) {
        //        var download = new DownloadOperation();
        //        download.load(downloads[i]);
        //        downloadOperations.push(download);
        //    }
        //});
        //不能使用循环下载，最好是使用队列排队下载
        //console.log(data);
        for (var i = 0; i < data.length; i++) {
            var DownloadOption = {
                saveLocation: "",    //保存地址
                folderName: "adfolder",      //保存的文件目录
                fileName: "xxx_" + data[i].Id + ".jpg",        //保存的文件名
                uriString: data[i].ImageURL    //下载的URL
            };

            DownloadOptionList.push(DownloadOption);
        }

        //先创建保存目录
        // Asynchronously create the file in the pictures folder.
        // 获取temp目录地址的对象，为storageFolder类
        var localFolder = Windows.Storage.ApplicationData.current.localFolder;

        console.log("下载保存路径：" + localFolder.path);

        //创建目录
        localFolder.createFolderAsync("adfolder", Windows.Storage.CreationCollisionOption.replaceExisting).then(function (newFolder) {
            console.log("createFolderAsync：OK------------------------------------------");

            //TODO: 开始下载执行
            startDownload(DownloadOptionList[0], newFolder);

        }, function () {
            console.log("createFolderAsync：error------------------------------------------");
        })

        console.log("downloadOperations");
        console.log(downloadOperations);
    }


    //TODO: 下载操作类，DownloadOperation，Class associated with each download.
    function DownloadOperation() {
        var download = null;
        var promise = null;
        var imageStream = null;

        //开始下载成员函数
        //参数：
        //uri：下载地址
        //fileName：保存文件名
        //priority：下载优先级
        //requestUnconstrainedDownload：
        this.start = function (uri, folderObj, fileName, priority, requestUnconstrainedDownload) {
            console.log("start：" + fileName + "------------------------------------------");
 
            // 创建文件对象，generateUniqueName：0，自动追加一个数字；replaceExisting：1，替换任何文件或文件夹     
            folderObj.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.replaceExisting).then(function (newFile) {
                console.log("createFileAsync：OK------------------------------------------");

                //新建后台传输类
                var downloader = new Windows.Networking.BackgroundTransfer.BackgroundDownloader();
                console.log("下载url: " + uri.absoluteUri);

                // newFile，类型: IStorageFile，响应将写入的文件。
                // 返回值：DownloadOperation类，下载操作
                download = downloader.createDownload(uri, newFile);

                // guid特定下载操作的唯一标识符。
                console.log("Created download " + download.guid + " with priority " +
                    (priority === Windows.Networking.BackgroundTransfer.BackgroundTransferPriority.high ? "high" : "default"));
                // 设置下载优先级
                download.priority = priority;

                // Unconstrained
                if (!requestUnconstrainedDownload) {
                    // 启动下载，并将下载操作存储在promise中，可以取消
                    //.then(1,2,3)的3个参数：
                    //一个是在承诺成功完成后调用的函数
                    //一个是在承诺完成但出错后调用的函数
                    //一个是提供进度信息的函数
                    promise = download.startAsync();
                    return promise;
                }
            },function () {
                console.log("createFileAsync：error------------------------------------------");
            }).then(function(){complete(folderObj);}, error, progress);
        };

        // On application activation, reassign callbacks for a download
        // operation persisted from previous application state.
        this.load = function (loadedDownload) {
            download = loadedDownload;
            printLog("Found download: " + download.guid + " from previous application run.<br\>");
            promise = download.attachAsync().then(complete, error, progress);
        };

        // Cancel download.
        this.cancel = function () {
            if (promise) {
                promise.cancel();
                promise = null;
                printLog("Canceling download: " + download.guid + "<br\>");
                if (imageStream) {
                    imageStream.close();
                    imageStream = null;
                }
            } else {
                printLog("Download " + download.guid + " already canceled.<br\>");
            }
        };

        // Resume download - download will restart if server does not allow range-requests.
        this.resume = function () {
            if (download) {
                if (download.progress.status === Windows.Networking.BackgroundTransfer.BackgroundTransferStatus.pausedByApplication) {
                    download.resume();
                    printLog("Resuming download: " + download.guid + "<br\>");
                } else {
                    printLog("Download " + download.guid +
                        " is not paused, it may be running, completed, canceled or in error.<br\>");
                }
            }
        };

        // Pause download.
        this.pause = function () {
            if (download) {
                if (download.progress.status === Windows.Networking.BackgroundTransfer.BackgroundTransferStatus.running) {
                    download.pause();
                    printLog("Pausing download: " + download.guid + "<br\>");
                } else {
                    printLog("Download " + download.guid +
                        " is not running, it may be paused, completed, canceled or in error.<br\>");
                }
            }
        };

        // Returns true if this is the download identified by the guid.
        this.hasGuid = function (guid) {
            return download.guid === guid;
        };

        // Removes download operation from global array.
        function removeDownload(guid) {
            downloadOperations.forEach(function (operation, index) {
                if (operation.hasGuid(guid)) {
                    downloadOperations.splice(index, 1);
                }
            });
        }

        // Progress callback.
        function progress() {
            // Output all attributes of the progress parameter.
            printLog(download.guid + " - progress: ");
            var currentProgress = download.progress;
            for (var att in currentProgress) {
                printLog(att + ": " + currentProgress[att] + ", ");
            }
            printLog("<br/>");

            // Handle various pause status conditions.
            // 暂停下载的各种情况
            if (currentProgress.status === Windows.Networking.BackgroundTransfer.BackgroundTransferStatus.pausedByApplication) {
                printLog("Download " + download.guid + " paused by application <br\>");
            } else if (currentProgress.status === Windows.Networking.BackgroundTransfer.BackgroundTransferStatus.pausedCostedNetwork) {
                printLog("Download " + download.guid + " paused because of costed network <br\>");
            } else if (currentProgress.status === Windows.Networking.BackgroundTransfer.BackgroundTransferStatus.pausedNoNetwork) {
                printLog("Download " + download.guid + " paused because network is unavailable.<br\>");
            } else {
                // 非暂停下载的情况
                // We need a response before assigning the result stream to the image: If we get a response from
                // the server (hasResponseChanged == true) and if we haven't assigned the stream yet
                // (imageStream == null), then assign the stream to the image.
                // There is a second scenario where we need to assign the stream to the image: If a download gets
                // interrupted and cannot be resumed, the request is restarted. In that case we need to re-assign
                // the stream to the image since the requested image may have changed.
                if ((currentProgress.hasResponseChanged && !imageStream) || (currentProgress.hasRestarted)) {
                    try {
                        // Get Content-Type response header.
                        var contentType = download.getResponseInformation().headers.lookup("Content-Type");

                        // Check the stream is an image. For an example, change the URI string of the 'serverAddressField'
                        // to 'http://localhost/BackgroundTransferSample/data/windows-sdk.png' and start a download.
                        if (contentType.indexOf("image/") === 0) {
                            // Get the stream starting from byte 0.//获取可能在指定位置下载的响应。
                            imageStream = download.getResultStreamAt(0);

                            // Convert the stream to MS-Stream.//MSApp对象传建一个文件流（blob或者ms自己的文件流）
                            var msStream = MSApp.createStreamFromInputStream(contentType, imageStream);
                            var imageUrl = URL.createObjectURL(msStream);

                            // Pass the stream URL to the HTML image tag.
                            id("imageHolder").src = imageUrl;

                            // Close the stream once the image is displayed.
                            id("imageHolder").onload = function () {
                                if (imageStream) {
                                    imageStream.close();
                                    imageStream = null;
                                }
                            };
                        }
                    } catch (err) {
                        printLog("<b>Error in outputting file:</b> " + err + "<br\>");
                    }
                }
            }
        }

        // Completion callback.
        function complete(folderObj) {
            console.log("startAsync：OK------------------------------------------");
            console.log("文件下载完成")
            removeDownload(download.guid);

            try {
                var responseInfo = download.getResponseInformation();// getResponseInformation 包含通过服务器响应返回的数据。
                console.log(download.guid + " - download complete. Status code: " + responseInfo.statusCode + "<br/>");
                displayStatus("Completed: " + download.guid + ", Status Code: " + responseInfo.statusCode);

                //先削减下载列表：DownloadOptionList里面的数据，是否可以和downloadOperations合并
                DownloadOptionList.splice(0, 1);
                //TODO: 执行下一次下载
                if (DownloadOptionList.length > 0) {
                    startDownload(DownloadOptionList[0], folderObj);
                }

            } catch (err) {
                displayException(err);
            }
        }

        // Error callback.
        function error(err) {
            console.log("startAsync：error------------------------------------------");

            if (download) {
                removeDownload(download.guid);
                console.log(download.guid + " - download completed with error.<br/>");
            }
            displayException(err);
        }
    }

    function displayException(err) {
        var message;
        if (err.stack) {
            message = err.stack;
        } else {
            message = err.message;
        }

        var errorStatus = Windows.Networking.BackgroundTransfer.BackgroundTransferError.getStatus(err.number);
        if (errorStatus === Windows.Web.WebErrorStatus.cannotConnect) {
            message = "App cannot connect. Network may be down, connection was refused or the host is unreachable.";
        }

        displayError(message);
    }

    function displayError(/*@type(String)*/message) {
        //WinJS.log && WinJS.log(message, "sample", "error");
        console.log("displayError："+message+"sample"+"error");
    }

    function displayStatus(/*@type(String)*/message) {
        //WinJS.log && WinJS.log(message, "sample", "status");
        console.log("displayStatus："+message + "sample" + "status");
    }

    // Print helper function.
    function printLog(/*@type(String)*/txt) {
        //var console = document.getElementById("outputConsole");
        //console.innerHTML += txt;
        //console.log("printLog："+txt);
    }

    function id(elementId) {
        return document.getElementById(elementId);
    }


    function startUnconstrainedDownload() {
        downloadFile(Windows.Networking.BackgroundTransfer.BackgroundTransferPriority.default, true);
    }

    function startHighPriorityDownload() {
        downloadFile(Windows.Networking.BackgroundTransfer.BackgroundTransferPriority.high, false);
    }
    //启动下载函数
    //参数：priority优先级，requestUnconstrainedTransfer：
    function downloadFile(priority, requestUnconstrainedTransfer, option) {
        // Instantiate downloads.
        var newDownload = new DownloadOperation();

        // Pass the uri and the file name to be stored on disk to start the download.
        //var fileName = document.getElementById("fileNameField").value;
        var fileName = option.fileName;
        if (fileName === "") {
            displayError("A local file name is required.");
            return;
        }

        // Validating the URI is required since it was received from an untrusted source (user input).
        // The URI is validated by catching exceptions thrown by the Uri constructor.
        // Note that when enabling the text box users may provide URIs to machines on the intrAnet that require the
        // "Home or Work Networking" capability.
        var uri = null;
        var uriString = option.uriString;

        try {
            //new Windows.Foundation.Uri()启动 URI 的默认应用//https://msdn.microsoft.com/zh-cn/library/windows/apps/hh452690.aspx?f=255&MSPPError=-2147217396
            uri = new Windows.Foundation.Uri(uriString);
        } catch (error) {
            console.log("Error: Invalid URI. " + error.message);
            return;
        }

        //fileName = "xxx.jpg";
        var folderName = option.folderName;

        newDownload.start(uri, folderName, fileName, priority, requestUnconstrainedTransfer);

        // Persist（存储） the download operation in the global array.
        downloadOperations.push(newDownload);
    }

    // Cancel all downloads.
    function cancelAll() {
        for (var i = 0; i < downloadOperations.length; i++) {
            downloadOperations[i].cancel();
        }
    }

    // Pause all downloads.
    function pauseAll() {
        for (var i = 0; i < downloadOperations.length; i++) {
            downloadOperations[i].pause();
        }
    }

    // Resume all downloads.
    function resumeAll() {
        for (var i = 0; i < downloadOperations.length; i++) {
            downloadOperations[i].resume();
        }
    }

})();
